home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CGAMEJOY.ARJ / JOYSTKLO.C < prev    next >
C/C++ Source or Header  |  1992-01-08  |  12KB  |  270 lines

  1. /* joystklo.c       Low level game-adapter port access functions.
  2.  
  3.                 The functions in this module
  4.                     1.  detect the presence of a game adapter
  5.                     2.  verify which axes are functional
  6.                     3.  read current button status
  7.                     4.  read changed button status
  8.                     5.  read current joystick resistance position
  9.                     6.  allow change of active axes within this system
  10.                         as long as they have been found functional.
  11.  
  12.                 See file joystklo.se for pseudo code/structured english
  13.                 and joystick.doc for an explanation of the functions.
  14.  
  15.                 This module was written for Borland C++ 2.0.
  16.                 No C++ extensions were used, this is all C and Assembler.
  17.  
  18.                 I've done limited testing on an old XT with 11/08/82 BIOS
  19.                 and on my PS/2 like 386 AT and haven't found anything yet...
  20.  
  21.                 If you find this module useful, great!!!
  22.  
  23.                 This module has been released to the public domain
  24.                         Tue  01-07-1992   23:30:18
  25.                 by Ed Torgerson : CIS 70313,456,  GEnie E.TORGERSON1.
  26.                 any constructive correspondence is welcome.
  27.  
  28.                 Thanks to Gary Blaine, for putting out JOY.ARC for all to use.
  29.  
  30. -----------------------------------------------------------------------------*/
  31.  
  32. #include <dos.h>
  33. #pragma inline
  34.  
  35. /*-- Global defines -----*/
  36. #define NOP       0x90  /* define NOP instruction for __emit__ delay */
  37. #define TIME_OUT  1000  /* one-shot time out value for reading position */
  38.                         /* N.B. Interrupts are disabled during timing */
  39.                         /* N.B. My loops are faster than Gary Blaine's, */
  40.                         /*      the TIME_OUT value is proportionally higher. */
  41.  
  42. /*-- Global variables -----*/
  43. unsigned char G_Stick_Active_Axes ;     /* bit mask of currently active axes */
  44. unsigned char G_Stick_Valid_Axes ;      /* bit mask of valid axes */
  45. unsigned char G_LastCallState = 0xF0 ;  /* bit image of last button state */
  46.  
  47. /*-- Function Prototypes -----*/
  48. int JstGetChangedButton( void ) ;       /* get changed button status */
  49. int JstGetButton( void ) ;              /* get present button status */
  50. int JstGetPosition(int axis_mask) ;     /* get position on given axis */
  51. int JstDetect ( void ) ;                /* detect active game port lines */
  52. int JstGetValidAxes ( void ) ;          /* return mask of valid axes */
  53. int JstGetActiveAxes( void ) ;          /* return mask of active axes */
  54. int JstSetActiveAxes( unsigned mask) ;  /* set mask of active axes */
  55.  
  56. /*-- Function Definitions ---------------------------------------------------*/
  57. int JstGetValidAxes ( void )            /* return bit mask of valid axes */
  58. {
  59.     return ( (unsigned) G_Stick_Valid_Axes ) ;
  60. }
  61. /*---------------------------------------------------------------------------*/
  62. int JstGetActiveAxes( void )             /* return bit mask of active axes */
  63. {
  64.     return ( (unsigned) G_Stick_Active_Axes ) ;
  65. }
  66. /*---------------------------------------------------------------------------*/
  67. int JstSetActiveAxes( unsigned mask )    /* set bit mask of active axes */
  68. {
  69.     asm {
  70.         mov     ax, mask                ;   /* get axis mask to set */
  71.         and     al, G_Stick_Valid_Axes  ;   /* set check value */
  72.         cmp     al, mask                ;   /* compare mask to check value */
  73.         je      ValidUserAxis           ;   /* valid if equal */
  74.     }
  75.     return ( 0 ) ;                          /* invalid mask */
  76. ValidUserAxis:
  77.     G_Stick_Active_Axes = (unsigned char) mask ;
  78.     return ( 1 ) ;                          /* success */
  79. }
  80. /*---------------------------------------------------------------------------*/
  81. int JstDetect ( )                 /* detect active game port lines */
  82. {
  83.     register unsigned char x, y ;
  84.  
  85.     outportb ( 0x201, 0 ) ;     /* initialize game adapter one-shot timers */
  86.     delay (200) ;               /* give the timers a chance to clear */
  87.     x = inportb ( 0x201 ) ;     /* get initial game adapter position flags */
  88.     x = x & 0xf ;               /* lose upper nibble */
  89.     outportb ( 0x201, 0 ) ;     /* initialize game adapter one-shot timers */
  90.     __emit__(NOP);
  91.     __emit__(NOP);
  92.     __emit__(NOP);
  93.     __emit__(NOP);
  94.     __emit__(NOP);
  95.     y = inportb ( 0x201 ) ;     /* get initial game adapter position flags */
  96.     y = y & 0xf ;               /* lose upper nibble */
  97.     x = x ^ y ;                 /* any axes that change are functional */
  98.     G_Stick_Active_Axes = x ;   /* set currently active axes */
  99.     G_Stick_Valid_Axes = x ;    /* set valid axes mask */
  100.     return ( (unsigned) x ) ;
  101. } /*-- end JstDetect */
  102.  
  103. /*---------------------------------------------------------------------------*/
  104. int JstGetButton()                    /* get present button status */
  105. {
  106.     asm {
  107.         mov     dx, 201h                ; /* port address of game adapter */
  108.         in      al, dx                  ; /* al = game port state */
  109.         and     al, 0xF0                ; /* lose lower nibble */
  110.         mov     G_LastCallState, al     ; /* save button state for next call */
  111.         xor     al, 0xF0                ; /* flip bits */
  112.         mov     dh, al                  ; /* dl = button down mask */
  113.         xor     al, 0xF0                ; /* al = button up mask */
  114.         mov     cl, 4
  115.         shr     al, cl                  ; /* shift mask to lower nibble */
  116.         or      al, dh                  ; /* al = combined button event mask */
  117.         xor     ah, ah                  ; /* zero out ah for return */
  118.     }
  119.     return (_AX) ;
  120. } /*-- end JstGetButton */
  121. /*---------------------------------------------------------------------------*/
  122. int JstGetChangedButton( )           /* get changed button status */
  123. {
  124.     asm {
  125.         mov     dx, 201h                ; /* port address of game adapter */
  126.         in      al, dx                  ; /* al = game port state */
  127.         and     al, 0xF0                ; /* lose lower nibble */
  128.         mov     dh, al                  ; /* dl = current button state */
  129.         xor     al, G_LastCallState     ; /* al = changed button mask */
  130.         jnz     ButtonChanged
  131.     }
  132.     return (0) ;
  133. ButtonChanged:
  134.     asm {
  135.         mov     dl, G_LastCallState     ; /* dl = last call state */
  136.         mov     G_LastCallState, dh     ; /* save button state for next call */
  137.         and     dl, al                  ; /* dl = button down mask */
  138.         xor     al, dl                  ; /* al = button up mask */
  139.         mov     cl, 4
  140.         shr     al, cl                  ; /* shift mask to lower nibble */
  141.  
  142.         or      al, dl                  ; /* al = combined button event mask */
  143.         xor     ah, ah                  ; /* zero out ah for return */
  144.     }
  145.     return (_AX) ;
  146. } /*-- end JstGetChangedButton */
  147. /*---------------------------------------------------------------------------*/
  148. int JstGetPosition(int axis_mask )    /* get position on given axis */
  149. {
  150.     asm {
  151.         mov     al, G_Stick_Active_Axes ; /* get currently active axes */
  152.         test    al, axis_mask           ; /* check if given axis is active */
  153.         jnz     ValidAxis               ; /* go on if valid */
  154.         }
  155.         return (0) ;                    /* error - invalid parameter given */
  156. ValidAxis:
  157.     asm {
  158.         cli                     ; /* disable interrupts for accurate timing */
  159.         mov     dx, 0x43        ; /* 8253 write command port */
  160.         xor     al, al          ; /* 8253 latch timer 0 command */
  161.         out     dx,al
  162.         nop                     ; /* delay so latch regs can be filled */
  163.         nop
  164.         nop
  165.         nop
  166.         nop
  167.         mov     dx, 0x40        ; /* 8253 read port */
  168.         in      al, dx          ; /* read low byte of 8253 timer count */
  169.         mov     cl, al          ; /* copy to CL */
  170.         nop                     ; /* delay so latch regs can be filled */
  171.         nop
  172.         nop
  173.         mov     dx, 0x40        ; /* 8253 read port */
  174.         in      al, dx          ; /* read high byte of 8253 timer count */
  175.         mov     ch, al          ; /* !!!! CX = start_time !!!!*/
  176.         push    cx              ; /* just to be safe */
  177.  
  178. ;----- /* Time to start timin' */
  179.         mov     dx, 0x201       ; /* write to game adapter */
  180.         mov     al, 0           ; /* initialize one-shot timers */
  181.         out     dx, al          ;
  182.  
  183.         xor     si, si          ; /* set up timing loop */
  184.         mov     bx, axis_mask   ; /* get axis mask for quick read */
  185.     }
  186. DoLoop1:
  187.     asm {
  188.         mov     dx, 0x201       ; /* read game adapter */
  189.         in      al, dx          ;
  190.         test    al, bl          ; /* test for matching bit */
  191.         jz      short DoneLoop1 ; /* go on if match */
  192.         inc     si              ;
  193.         cmp     si, TIME_OUT    ; /* quit if timed out */
  194.         jz      short Quit0     ;
  195.         jmp     short DoLoop1   ; /* loop back */
  196.     }
  197. Quit0:
  198.     asm {
  199.         sti                     ; /* re-enable interrupts */
  200.     }
  201.         return (0) ;            ; /* error - loop timed out */
  202. DoneLoop1:
  203.     asm {
  204.         mov     dx, 0x43        ; /* 8253 write command port */
  205.         xor     al, al          ; /* 8253 latch timer 0 command */
  206.         out     dx,al
  207.         nop                     ; /* delay so latch regs can be filled */
  208.         nop
  209.         nop
  210.         nop
  211.         nop
  212.         mov     dx, 0x40        ; /* 8253 read port */
  213.         in      al, dx          ; /* read low byte of 8253 timer count */
  214.         mov     bl, al          ; /* copy to BL */
  215.         nop                     ; /* delay so latch regs can be filled */
  216.         nop
  217.         nop
  218.         mov     dx, 0x40        ; /* 8253 read port */
  219.         in      al, dx          ; /* read high byte of 8253 timer count */
  220.         mov     bh, al          ; /* !!!! BX = finish_time !!!! */
  221.         sti                     ; /* re-enable interrupts */
  222.     }
  223.     asm {
  224.         pop     cx                  ; /* start time */
  225.         cmp     cx, bx              ; /* jump if start < finish */
  226.         jb      short StartIsLess
  227.         sub     cx, bx              ; /*  result = start - finish; */
  228.         mov     ax, cx              ; /* !!!! AX = result !!!! */
  229.         jmp     short AdjustResult
  230.     }
  231. StartIsLess:
  232.     asm {
  233.         mov     ax, 65535           ; /* result = 0xffff - finish + start */
  234.         sub     ax, bx
  235.         add     ax, cx              ; /* !!!! AX = result !!!! */
  236.     }
  237. AdjustResult:
  238.     asm {
  239.         and     ax, 8176            ; /* result & 0x1ff0 */
  240.         mov     cl, 4               ;
  241.         shr     ax, cl              ; /* result = result >> 4 */
  242.         push    ax                  ; /* save ax */
  243.  
  244.         xor     si, si              ; /* set up loop to clear rest of bits */
  245.         mov     cl, G_Stick_Valid_Axes  ; /* get mask of valid axes */
  246.         not     cl                  ; /* flip axis mask for test */
  247.         and     cl, 0xf             ; /* just to be sure... */
  248.     }
  249. DoLoop2:
  250.     asm {
  251.         mov     dx, 0x201       ; /* read game adapter */
  252.         in      al, dx          ;
  253.         and     al, 0xf         ; /* lose upper nibble */
  254.         cmp     al, cl          ; /* check if all bits have flipped */
  255.         jz      DoneLoop2       ; /* jump if we're done */
  256.         inc     si              ; /* increment counter */
  257.         cmp     si, TIME_OUT    ; /* quit if timed out */
  258.         jz      short DoneLoop2
  259.         jmp     short DoLoop2   ; /* loop back */
  260.     }
  261. DoneLoop2:
  262.     asm {
  263.         pop     ax              ; /* get back our result */
  264.     }
  265.     return (_AX) ;
  266. } /* end JstGetPosition */
  267. /*---------------------------------------------------------------------------*/
  268.  
  269. /* end joystklo.c */
  270.